package org.cybzacg.convert.converters.gather;

import org.cybzacg.convert.annotation.Converter;
import org.cybzacg.convert.enums.ConversionError;
import org.cybzacg.convert.enums.ConversionPriority;
import org.cybzacg.convert.enums.ConversionType;
import org.cybzacg.convert.exception.ConversionException;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * Set类型转换器
 * 支持各种Set类型之间的转换
 *
 * @author cybzacg.blog
 * @version 4.0
 * @since 3.0
 */
@Slf4j
@Converter(name = "SetConverter", priority = ConversionPriority.MEDIUM, description = "Set类型转换器，支持各种Set类型之间的转换", enabled = true, version = "4.0", author = "cybzacg.blog", supportedTypes = {
        Set.class }, tags = { "set", "collection", "conversion" })
public class SetConverter extends AbstractCollectionConverter<Set<Object>> {

    // Set类型实现类映射
    private static final Map<Class<?>, Class<?>> SET_IMPLEMENTATIONS = new HashMap<>();

    static {
        SET_IMPLEMENTATIONS.put(Set.class, HashSet.class);
        SET_IMPLEMENTATIONS.put(AbstractSet.class, HashSet.class);
        SET_IMPLEMENTATIONS.put(SortedSet.class, TreeSet.class);
        SET_IMPLEMENTATIONS.put(NavigableSet.class, TreeSet.class);
    }

    public SetConverter() {
        super(Set.class, ConversionPriority.MEDIUM);
    }

    @Override
    protected ConversionType getConversionType() {
        return ConversionType.SET;
    }

    @Override
    @SuppressWarnings("unchecked")
    protected <T> Set<Object> createEmptyCollection(Class<T> targetType) {
        try {
            // 如果是具体的Set实现类，直接实例化
            if (Set.class.isAssignableFrom(targetType) &&
                    !targetType.isInterface() &&
                    !java.lang.reflect.Modifier.isAbstract(targetType.getModifiers())) {
                return (Set<Object>) targetType.getDeclaredConstructor().newInstance();
            }

            // 根据接口类型选择实现类
            Class<?> implementationClass = SET_IMPLEMENTATIONS.get(targetType);
            if (implementationClass != null) {
                return (Set<Object>) implementationClass.getDeclaredConstructor().newInstance();
            }

            // 根据目标类型特征选择合适的实现
            if (targetType.getName().contains("TreeSet") ||
                    targetType.getName().contains("Sorted") ||
                    targetType.getName().contains("Navigable")) {
                return new TreeSet<>();
            } else if (targetType.getName().contains("LinkedHashSet")) {
                return new LinkedHashSet<>();
            } else if (targetType.getName().contains("CopyOnWrite")) {
                return new CopyOnWriteArraySet<>();
            } else if (targetType.getName().contains("ConcurrentSkipList")) {
                return new ConcurrentSkipListSet<>();
            }

            // 默认使用HashSet
            return new HashSet<>();

        } catch (Exception e) {
            throw new ConversionException(ConversionError.CONVERSION_FAILED,
                    "无法创建Set实例: " + targetType.getSimpleName(), e);
        }
    }

    @Override
    protected String getDefaultMapConversionMode() {
        return "keys"; // Set默认转换Map的keys（自动去重）
    }

    @Override
    public String getName() {
        return "SetConverter";
    }

    // ========== 静态工具方法 ==========

    /**
     * 检查是否为Set类型
     */
    public static boolean isSetType(Class<?> clazz) {
        return Set.class.isAssignableFrom(clazz);
    }

    /**
     * 创建HashSet的便捷方法
     */
    public static HashSet<Object> toHashSet(Object source) {
        SetConverter converter = new SetConverter();
        try {
            return (HashSet<Object>) converter.convertToCollection(source, HashSet.class, null);
        } catch (Exception e) {
            throw new ConversionException(ConversionError.CONVERSION_FAILED,
                    "转换为HashSet失败: " + source, e);
        }
    }

    /**
     * 创建TreeSet的便捷方法
     */
    public static TreeSet<Object> toTreeSet(Object source) {
        SetConverter converter = new SetConverter();
        try {
            return (TreeSet<Object>) converter.convertToCollection(source, TreeSet.class, null);
        } catch (Exception e) {
            throw new ConversionException(ConversionError.CONVERSION_FAILED,
                    "转换为TreeSet失败: " + source, e);
        }
    }

    /**
     * 检查Set是否为空或null
     */
    public static boolean isEmpty(Set<?> set) {
        return set == null || set.isEmpty();
    }

    /**
     * 获取Set的安全大小
     */
    public static int safeSize(Set<?> set) {
        return set != null ? set.size() : 0;
    }
}
